﻿#include "LETdMessenger.hh"

#include "G4ScoringManager.hh"
#include "G4SystemOfUnits.hh"
#include "G4Tokenizer.hh"
#include "G4UIcmdWithAString.hh"
#include "G4UIdirectory.hh"
#include "G4UImanager.hh"
#include "G4VScoringMesh.hh"
#include "PSSDoseAveragedLET.hh"

LETdMessenger::LETdMessenger()
{
    fDir = new G4UIdirectory("/letd/");
    fDir->SetGuidance("Commands for dose-averaged LET (LETd) scoring.");
    //------
    fAddToMesh = new G4UIcmdWithAString("/letd/addToMesh", this);
    fAddToMesh->SetGuidance("Attach a dose-averaged LET scorer to a scoring mesh.");
    fAddToMesh->SetGuidance("Usage: /letd/addToMesh <meshName> [primitiveName]");
    fAddToMesh->SetParameterName("meshName primitiveName", false);
}

LETdMessenger::~LETdMessenger()
{
    delete fAddToMesh;
    delete fDir;
}

void LETdMessenger::SetNewValue(G4UIcommand* cmd, G4String val)
{
    if (cmd == fAddToMesh)
    {
        // 解析参数：<meshName> [psName]
        G4Tokenizer next(val);
        G4String meshName = next();
        if (meshName.empty() || meshName == "")
        {
            G4Exception("LETdMessenger::SetNewValue", "LETD001", JustWarning, "Missing meshName. Usage: /letd/addToMesh <meshName> [primitiveName]");
            return;
        }
        G4String psName = next();
        if (psName.empty() || psName == "")
        {
            psName = "LETd";
        }

        G4cout << "[LETdMessenger] addToMesh called on " << (G4Threading::IsWorkerThread() ? "WORKER" : "MASTER") << ", mesh=" << meshName
               << ", psName=" << psName << G4endl;

        auto* sm = G4ScoringManager::GetScoringManagerIfExist();
        if (!sm)
        {
            G4Exception("LETdMessenger::SetNewValue", "LETD002", JustWarning, "G4ScoringManager not found. Did you enable scoring?");
            return;
        }

        // 按名称查找 mesh，并将 primitive 加上去
        G4VScoringMesh* mesh = sm->FindMesh(meshName);
        if (!mesh)
        {
            G4String msg = "Mesh '" + meshName + "' not found.";
            G4Exception("LETdMessenger::SetNewValue", "LETD003", JustWarning, msg);
            return;
        }

        sm->SetCurrentMesh(mesh);

        G4cout << "[LETdMessenger] Before addToMesh: current mesh = " << (sm->GetCurrentMesh() ? sm->GetCurrentMesh()->GetWorldName() : "NULL")
               << G4endl;

        // 将 LETd primitive 注册到该 mesh
        if (!mesh->FindPrimitiveScorer(psName))
        {
            auto* scorer = new PSSDoseAveragedLET(psName);
            mesh->SetPrimitiveScorer(scorer);
            G4cout << "[LETdMessenger] Primitive '" << psName << "' attached to mesh '" << meshName << "'.\n";
        }
    }
}
